package nl.vu.few.ibivu.biomodels.client;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Singleton;

import nl.vu.few.ibivu.biomodels.shared.Model;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.types.FieldType;
import com.smartgwt.client.widgets.grid.ListGridRecord;

public class ModelDataSource extends GwtRpcDataSource {
	
	private ModelServiceAsync ms;
	
	@Inject
	@Singleton
	public ModelDataSource(ModelServiceAsync ms) {
		super();
		this.ms = ms;
		setAutoDeriveTitles(false);
		
		DataSourceField idField =
        	new DataSourceField("id", FieldType.INTEGER, "ID");
		idField.setPrimaryKey(true);
		idField.setHidden(true);
		DataSourceField nameField =
        	new DataSourceField("name", FieldType.TEXT, "Name");
		DataSourceField ispublicField =
        	new DataSourceField("ispublic", FieldType.BOOLEAN, "Published");
		DataSourceField descriptionField =
			new DataSourceField("description", FieldType.TEXT, "Description");
		descriptionField.setHidden(true);
		DataSourceField thumbnailField =
			new DataSourceField("thumbnail", FieldType.IMAGE, "Description");
		thumbnailField.setHidden(true);
		DataSourceField creationTime = 
			new DataSourceField("creationTime", FieldType.DATETIME, "Created");
		DataSourceField modifiedTime = 
			new DataSourceField("modifiedTime", FieldType.DATETIME, "Modified");
		
		setFields(idField, nameField, ispublicField, descriptionField, creationTime, modifiedTime, thumbnailField);
		
	}

	private void copyValues(Model model, ListGridRecord record) {
		record.setAttribute("id", model.getId());
		record.setAttribute("name", model.getName());
		record.setAttribute("ispublic", model.isPublic());
		record.setAttribute("description", model.getDescription());
		record.setAttribute("creationTime", model.getCreationTime());
		record.setAttribute("modifiedTime", model.getModifiedTime());
		String thumbnail = model.getThumbnail();
		if (thumbnail != null && !thumbnail.isEmpty()) {
			thumbnail = "data:image/png;base64," + thumbnail;
		}
		else {
			thumbnail = null;
		}
		record.setAttribute("thumbnail", thumbnail);
	}

	@Override
	protected void executeFetch(final String requestId, DSRequest request, final DSResponse response) {
		final Integer startRow = request.getStartRow();
		final Integer endRow = request.getEndRow();
		ms.fetch(
				startRow,
				endRow,
				// we can't use request.getSortBy() here because it throws a ClassCastException (known bug).
				// TODO: replace with request.getSortBy() as soon as the bug is fixed.
				request.getAttribute("sortBy"), 
				new AsyncCallback<GwtRpcResultList<Model>>() {
					
			public void onFailure(Throwable caught) {
				response.setStatus(RPCResponse.STATUS_FAILURE);
				response.setAttribute("errorMessage", caught.getMessage());
				processResponse(requestId, response);
			}

			public void onSuccess(GwtRpcResultList<Model> result) {
				List<ListGridRecord> records = new ArrayList<ListGridRecord>();
				for (Model data : result) {
					ListGridRecord newRec = new ListGridRecord();
					copyValues(data, newRec);
					records.add(newRec);
				}
				Integer totalRows = result.getTotalRows();
				response.setStartRow(startRow);
				response.setEndRow(Math.min(endRow, totalRows));
				response.setTotalRows(totalRows);
					
				response.setData(records.toArray(new Record[records.size()]));
				processResponse(requestId, response);
			}
		});
	}

	@Override
	protected void executeAdd(String requestId, DSRequest request, DSResponse response) {
		throw new UnsupportedOperationException();
	}

	@Override
	protected void executeUpdate(String requestId, DSRequest request, DSResponse response) {
		throw new UnsupportedOperationException();
	}

	@Override
	protected void executeRemove(final String requestId, DSRequest request, final DSResponse response) {
		final ListGridRecord record = new ListGridRecord();
		record.setJsObj(request.getData());
		Long modelId;
		try {
			modelId = Long.valueOf(record.getAttributeAsString("id"));
		}
		catch(NumberFormatException e) {
			response.setStatus(RPCResponse.STATUS_FAILURE);
			processResponse(requestId, response);
			return;
		}
		ms.remove(modelId, new AsyncCallback<Void>() {
			public void onFailure(Throwable caught) {
				response.setStatus(RPCResponse.STATUS_FAILURE);
				processResponse(requestId, response);
			}

			public void onSuccess(Void v) {
				response.setStatus(RPCResponse.STATUS_SUCCESS);
				processResponse(requestId, response);
			}

		});
	}
}
